Conditional Processing
Many elements can be enclosed in elements called <if> or have optional child elements called <condition>. These enable conditional processing which will determine if the parent element will be processed or ignored.
Schema
<if [scan|identifier]
[isEmpty="true|false"]
[equals="{some-text}"]
[contains="{some-text}"]
[notContains="{some-other-text}"]
[containsOneOf="{text1},{text2},{text3},..."]
[equalsIdentifier="identifier-name"]
[containsIdentifier="identifier-name"]
[notContainsIdentifier="identifier-name"]
[matches="regex-expression"]
[organisation="int"]
[notOrganisation="int"]
[template="int"]
[notTemplate="int"]
[user="int"]
[notUser="int"]
[group="int"]
[notGroup="int"]
[status="status-name"]
[notStatus="status-name"]
[class="class-name"]
[chroma="chroma-name"]
[plex="plex-name"]
[autoGenerated="true|false"]
[electronicDelivery="true|false"]
[isValidEmail="true|false"] >
</if>
Attributes
<if equals="some-text" />
Evaluates to TRUE if the scanned text/identifier equals "some-text". "some-text" cannot contain wildcards, i.e. '*' and '?' are intepreted as ordinary characters. The comparison is not case-sensitive.
<if contains="some-text" /> and <if notContains="some-text" />
Evaluates to TRUE if the scanned text/identifier contains (or does not contain) "some-text". "some-text " can contain wildcards e.g. '?' and '*'.
<if containsOneOf="text1,text2,text3,..." />
Evaluates to TRUE if the scanned text/identifier contains at least one of "text1", "text2", "text3" etc. Wildcards are not supported with this attribute.
<if equalsIdentifier="identifier-name" />
Evaluates to TRUE if the scanned text/identifier equals the value of the identifier named "identifier-name". Wildcards are not supported with this attribute.
<if containsIdentifier="identifier-name" /> and <if notContainsIdentifier="identifier-name" />
Evaluates to TRUE if the scanned text/identifier contains (or does not contain) the value of the identifier named "identifier-name". Wildcards are not supported with this attribute.
<if matches="regex" />
Evaluates to TRUE if the scanned text/identifier matches the regular expression "regex".
<if isEmpty="true|false" />
Evaluates to TRUE if the scanned text/identifier is (or is not, depending on the boolean value) an empty string.
<if isValidEmail="true|false" />
Evaluates to TRUE if the scanned text/identifier is (or is not, depending on the boolean value) a valid format for an email address. N.B. only the format is checked, not whether the email address is the correct one.
<if organisation="int" /> and <if notOrganisation="int" />
Evaluates to TRUE if the letter was submitted by the organisation whose ID is (or is not) 'int'.
<if template="int" /> and <if notTemplate="int" />
Evaluates to TRUE if the letter was submitted using the template whose ID is (or is not) 'int'.
<if group="int" /> and <if notGroup="int" />
Evaluates to TRUE if the letter was submitted by a user whose reporting group has (or has not) a ID of 'int'.
<if user="int" /> and <if notUser="int" />
Evaluates to TRUE if the letter was submitted by a user whose whose ID is (or is not) 'int'.
<if status="status-name" /> and <if status="status-name" />
Evaluates to TRUE if the current letter status is (or is not) 'status-name'.
N.B this requires the status name: e.g. 'pending', not the numerical status value.
Valid status names are 'pending', 'queued', outputAssigned', 'rejected, 'deleted'.
<if class="class-name" />
Evaluates to TRUE if the current letter class is equal to 'class-name'.
Valid class names are 'first', 'second'.
<if chroma="chroma-name" />
Evaluates to TRUE if the current letter chroma is equal to 'chroma-name'.
Valid chroma names are 'mono', 'colour'.
<if plex="plex-name" />
Evaluates to TRUE if the current letter plex is equal to 'plex-name'.
Valid plex names are 'duplex', 'simplex'.
<if autoGenerated="true|false" />
Evaluates to TRUE if the letter was (or was not, depending on the boolean value) generated by HybridMail rather than submitted by a user.
<if electronicDelivery="true|false" />
Evaluates to TRUE if the letter is (or is not, depending on the boolean value) destined to be sent via an electronic delivery method rather than by post..
<if> vs. <condition>
The schema for the <if> and <condition> elements is identical. The difference is that the <if> wraps the element to be conditionally processed, whereas the <condition> is a child of it.
<if scan="20,20,20,20" contains="harry" >
<setIdentifier name="category">wizard</setIdentifier>
</if>
<setIdentifier name="category">wizard
<condition scan="20,20,20,20" contains="harry" />
</setIdentifier>
The <if> element is more versatile because it can enclose multiple child elements, which can themselves be nested within other <if> elements. The <condition> elements is a simpler and more elegant way of conditionally processing a single element.
Very Important!!
Regardless of the order in which they are written in the XML file, the attributes are processed in the order shown in the schema. If any attribute evaluates to FALSE, then processing stops and the whole <if> or <condition> is declared FALSE.
Examples
The following will change the status to Rejected.
<letterStatus">rejected</letterStatus>
The following will change the status to Rejected, but only if the scan area '20,20,20,20' contains 'fred'
<if scan="20,20,20,20" contains="fred" >
<letterStatus">rejected</letterStatus>
</if>
<!-- alternatively -->
<letterStatus>rejected
<condition scan="20,20,20,20" contains="fred" />
</letterStatus>
You can use containsIdentifier instead of contains, in which case the scanned text is compared with the contents of the identifier whose name is specified. Obviously in this case, you cannot use wildcards! In this example, the region '20,20,20,20' is being examined to see if it contains the letter postcode.
<setIdentifier name="identB" letterValue="postcode">
<if scan="20,20,20,20" containsIdentifier="identB" >
<!-- these lines will be executed if the
scanned area contains the letter postcode -->>
</if>
You can nest <if> elements multiple levels deep and enclose multiple other elements.
<if scan="20,20,20,20" contains="fred">
<letterClass>first</letterClass>
<letterOutput>27</letterOutput>
<if scan="30,30,30,30" contains="george">
<if scan="40,40,40,40" contains="harry">
<letterStatus>rejected</letterStatus>
</if>
</if>
</if>
You can AND <condition> elements together by having more than one of them.
E.g. The following will change the status to 'rejected', but only if the scan area '20,20,20,20' contains 'fred' AND the scan area '30,30,30,30' contains 'george'
<letterStatus>rejected
<condition scan="20,20,20,20" contains="fred"/>
<condition scan="30,30,30,30" contains="george"/>
</letterStatus>
You can OR <condition> elements together by having more than one of the whole parent element.
E.g. The following will change the status to 'rejected', but only if the scan area '20,20,20,20' contains 'fred' OR the scan area '30,30,30,30' contains 'george'
<letterStatus>rejected
<condition scan="20,20,20,20" contains="fred"/>
</letterStatus>
<letterStatus>rejected
<condition scan="30,30,30,30" contains="george"/>
</letterStatus>
You can use matches="regex" to search for a substring within the scanned text that matches the regular expression.
E.g. The following statement is TRUE if the scanned text consists of two lower-case characters and one numeric character.
<if scan="20,20,20,20" matches="[a-z]{2}[0-9]">
</if>
Nota bene!
The <if> element behaves slightly differently from the <condition> element when the scanned text is empty.
<if scan="30,30,30,30" contains="george"> <!-- is FALSE if scan text is empty, meaning -->
<letterStatus>rejected</letterStatus> <!-- this element will NOT be executed -->
</if>
<if scan="30,30,30,30" notContains="george"> <!-- is TRUE if scan text is empty, meaning -->
<letterStatus>rejected</letterStatus> <!-- this element will be executed -->
</if>
The <condition> element requires scanned text to operate. If the scan text is empty then the condition is ignored and the parent element is processed as if the condition did not exist.
<condition scan="30,30,30,30" contains="george" /> <!-- is TRUE if scan text is empty -->
<condition scan="30,30,30,30" notContains="george" /> <!-- is TRUE if scan text is empty -->
If you want a <condition> element to be FALSE when the scan area is empty, place a character (e.g. x ) as the default scan text, or use the isEmpty attribute.
<condition scan="30,30,30,30" contains="george">x</condition> <!-- is FALSE if scan text is empty -->
<condition scan="30,30,30,30" contains="george" isEmpty="false" /> <!-- is FALSE if scan text is empty -->